package com.hk.blog.controller;

import com.hk.blog.domain.Menu;
import com.hk.blog.service.MenuService;
import com.hk.commons.JsonResult;
import com.hk.commons.query.Order;
import com.hk.commons.query.QueryModel;
import com.hk.commons.query.page.SimpleQueryPage;
import com.hk.commons.util.CollectionUtils;
import com.hk.commons.util.Constants;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;


/**
 * @author Kevin
 */
@RequiredArgsConstructor
@RestController
@RequestMapping("menu")
public class MenuController {

    private final MenuService menuService;

    @PostMapping("list")
    public JsonResult<?> list(@RequestBody QueryModel<Menu> query) {
        query.getParam().setParentId(Constants.DEFAULT_VALUE_LONG);
        query.addOrderToFirst(Order.asc("sortBy"));
        var page = menuService.queryForPage(query);
        var result = toTableTree(page.getData());
        return JsonResult.success(new SimpleQueryPage<>(result, page.getTotalRow(), page.getPageIndex(), page.getPageSize()));
    }

    private List<Map<String, ?>> toTableTree(List<Menu> menuList) {
        Set<Long> ids = menuList.stream().map(Menu::getId).collect(Collectors.toSet());
        Map<Long, List<Menu>> childMapGroupId = menuService.findByParentIds(ids)
                .stream().collect(Collectors.groupingBy(Menu::getParentId));
        return menuList.stream().map(item -> {
            Map<String, Object> m = new HashMap<>();
            m.put("id", item.getId());
            m.put("menuName", item.getMenuName());
            m.put("path", item.getPath());
            m.put("icon", item.getIcon());
            if(!Objects.equals(item.getParentId(),Constants.DEFAULT_VALUE_LONG)){
                m.put("parentId", item.getParentId());
            }
            m.put("sortBy", item.getSortBy());
            m.put("component", item.getComponent());
            List<Menu> childMenus = childMapGroupId.get(item.getId());
            if (CollectionUtils.isNotEmpty(childMenus)) {
                m.put("children", toTableTree(childMenus));
            }
            return m;
        }).collect(Collectors.toList());
    }

    @PostMapping("children")
    public JsonResult<?> list(@RequestParam(value = "parentId") Long parentId) {
        return JsonResult.success(menuService.findByParentId(parentId));
    }


    @GetMapping("tree")
    public JsonResult<?> treeMenu() {
        List<Menu> menuList = menuService.findByParentId(Constants.DEFAULT_VALUE_LONG);
        return JsonResult.success(toTreeList(menuList));
    }

    private List<Map<String, ?>> toTreeList(List<Menu> menuList) {
        return menuList.stream()
                .map(item -> {
                    List<Menu> childrenMenuList = menuService.findByParentId(item.getId());
                    boolean isLeaf = childrenMenuList.isEmpty();
                    List<Map<String, ?>> children = null;
                    if (!isLeaf) {
                        children = toTreeList(childrenMenuList);
                    }
                    var m = new HashMap<String, Object>();
                    m.put("value", item.getId());
                    m.put("isLeaf", isLeaf);
//                    m.put("disabled", !isLeaf);
                    m.put("title", item.getMenuName());
                    if (!isLeaf) {
                        m.put("children", children);
                    }
                    return m;
                })
                .collect(Collectors.toList());
    }


    @GetMapping("get")
    public JsonResult<?> get(Long id) {
        Menu menu = menuService.findById(id).orElse(new Menu());
        return JsonResult.success(Map.of("menu", menu, "parentList", menuService.findByParentId(Constants.DEFAULT_VALUE_LONG)));
    }

    @PostMapping("delete")
    public JsonResult<?> deleteById(Long id) {
        menuService.deleteById(id);
        return JsonResult.success();
    }

    @PostMapping("save")
    public JsonResult<?> saveOrUpdate(@RequestBody Menu menu) {
        menuService.insertOrUpdate(menu);
        return JsonResult.success();
    }
}
